package com.sparrow.socket.manager;

import com.sparrow.common.util.ByteBuddyUtil;
import com.sparrow.common.util.PropertiesUtil;
import com.sparrow.common.event.IEventInvoker;
import com.sparrow.event.core.EventBusImpl;
import com.sparrow.event.receiver.impl.EventReceiver;
import com.sparrow.socket.tcp.anno.PacketHandler;
import com.sparrow.socket.anno.Packet;
import com.sparrow.socket.util.PacketHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

public class PacketHandlerManager implements ApplicationListener<ContextRefreshedEvent > {

    private ConcurrentHashMap<Integer, IEventInvoker> invokerMap = new ConcurrentHashMap<>();


    private static final AtomicBoolean initFlag = new AtomicBoolean(false);

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    EventBusImpl eventBus;

    private void scanAndRegister() {
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PacketHandler.class);
        for (Object bean : beansWithAnnotation.values()) {
            Class<?> clazz = bean.getClass();
            for (Method method : clazz.getDeclaredMethods()) {
                if (method.getName().startsWith("lambda$")) {
                    continue;
                }
                com.sparrow.event.annotation.EventReceiver eventAnno = method.getAnnotation(com.sparrow.event.annotation.EventReceiver.class);
                if (eventAnno == null) {
                    continue;
                }
                for (Class<?> parameterType : method.getParameterTypes()) {
                    Packet annotation = parameterType.getAnnotation(Packet.class);
                    if (annotation != null) {
                        int msgId = annotation.msgId();
                        try {
                            IEventInvoker methodWrapper = ByteBuddyUtil.generateInvoker(bean.getClass(), method, bean);
                            IEventInvoker pre = invokerMap.put(msgId, methodWrapper);
                            if (pre != null) {
                                throw new RuntimeException("消息方法 重复了 msgId:" + msgId);
                            }
                            eventBus.registerEventReceiver(parameterType, new EventReceiver(methodWrapper, eventAnno.order()));
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }
    }

    public IEventInvoker getInvoker(int msgId) {
        return invokerMap.get(msgId);
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 获取 Spring Environment
        if (initFlag.compareAndSet(false, true)) {
//            scanAndRegister();

            String path = PropertiesUtil.getProperty("msg.package.path");
            PacketHelper.init(path);
        }
    }


}
